#include "cudpserverthread.h"

CUdpServerThread::CUdpServerThread()
{
    mGPara = CGloble::getInstance();
}

int CUdpServerThread::Run()
{
    prctl(PR_SET_NAME, (unsigned long)"CUdpServerThread");
    int server_fd, ret;
    struct sockaddr_in ser_addr;
    server_fd = socket(AF_INET, SOCK_DGRAM, 0); //AF_INET:IPV4;SOCK_DGRAM:UDP
    if(server_fd < 0)
    {
        printf("create socket fail!\n");
        return -1;
    }

    memset(&ser_addr, 0, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址，需要进行网络序转换，INADDR_ANY：本地地址
    ser_addr.sin_port = htons(SERVER_PORT);  //端口号，需要网络序转换

    ret = bind(server_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
    if(ret < 0)
    {
        printf("socket bind fail!\n");
        return -1;
    }

    handle_udp_msg(server_fd);   //处理接收到的数据

    close(server_fd);
    return 0;
}

void CUdpServerThread::handle_udp_msg(int fd)
{

    char mode;
    socklen_t len;
    int count;
    char *buff; // 缓冲区指针
    char *bufflag = NULL;
    struct sockaddr_in clent_addr;  //clent_addr用于记录发送方的地址信息
    int rcvsize = 0;
    /* 分配缓冲区内存空间 */
    buff = (char*)malloc(IMAGE_SIZE);
    bufflag = (char*)malloc(READ_BUFF_LEN);
    SUdpDataHead* udp_head = (SUdpDataHead*)malloc(sizeof(SUdpDataHead));

    udp_head->mSendMask=0;
    udp_head->mRcvMask=0;
    if (NULL == buff || NULL == bufflag)   // 检查分配空间是否成功
    {
        fprintf(stderr, "molloc failed\n");
        return;
    }

    len = sizeof(clent_addr);

    int flag = 0;

    Mat receiveImg;
    string img_name;

    SUdpData tmp;

    int CUdpServerThread_Count = 0;

    while(1)
    {
        count = recvfrom(fd, udp_head, sizeof(SUdpDataHead), 0, (struct sockaddr*)&clent_addr, &len);
        if(count != sizeof(SUdpDataHead)||udp_head->mRcvMask!=0||udp_head->mHeadMark!=HEAD_MARK)
        {
            
            // printf("count != sizeof(SUdpDataHead)||udp_head->mHeadMark!=HEAD_MARK\n");
            // printf("rcv count: %d, local count: %d; RcvMask: %d, HeadMark: %d\n", count, sizeof(SUdpDataHead), udp_head->mRcvMask, udp_head->mHeadMark);
            continue;
        }
        else
        {
            printf("frame_idx: %d\n",udp_head->mIndex);
        }

        while(1)
        {
            flag = 0;
            rcvsize = 0;
            while (1)
            {
                count = recvfrom(fd, buff+flag*READ_BUFF_LEN, READ_BUFF_LEN, 0, (struct sockaddr*)&clent_addr, &len);  //recvfrom是拥塞函数，没有数据就一直拥塞
                if(count == -1)
                {
                    printf("recieve data fail!\n");
                    return;
                }
                else if(count == 0)
                {
                    continue;
                }
                else if(count!= READ_BUFF_LEN)
                {
                    cout << "count: " << count << endl;
                    break;
                }
                memset(bufflag, 0, READ_BUFF_LEN);
                rcvsize += count;
                if(rcvsize >= IMAGE_SIZE)
                {
                    break;
                }
                flag++;
            }

            if(rcvsize != IMAGE_SIZE)
            {
                cout << "flag = "<< flag<<endl;
                cout << "fail rcv the pic date  rcvsize = " <<rcvsize <<endl;
                memset(buff, 0, IMAGE_SIZE);
                goto RCVERROR;
            }
            if(CHANNEL_NUM==1)receiveImg = Mat(R_IMAGE_ROW,R_IMAGE_LINE,CV_8UC1,buff);
            else receiveImg = Mat(R_IMAGE_ROW,R_IMAGE_LINE,CV_8UC3,buff);
            tmp.src = receiveImg.clone();
            udp_head->mRcvMask |= SEND_SRC;
            memset(buff, 0, IMAGE_SIZE);

            if(udp_head->mSendMask == udp_head->mRcvMask)
            {
                mGPara->pushQue(*udp_head,tmp);
                CUdpServerThread_Count++;
                // printf("CUdpServerThread_Count=%d\n",CUdpServerThread_Count);
                mGPara->m_semUdp.Post();
                break;
            }
        }
RCVERROR:
        if(udp_head->mSendMask != udp_head->mRcvMask)
        {
            cout<<"udp_head->mSendMask != udp_head->mRcvMask"<<endl;
            continue;            
        }
    }
    free(buff);
    free(bufflag);
}
